/**
 * Created with IntelliJ IDEA.
 * User: alex
 * Date: 01.11.13
 * Time: 14:00
 * SVN $Id: MainClass.java 73 2013-12-23 15:42:14Z kuzn2k@gmail.com $
 */


package study.alex.resumedb;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialogs;
import study.alex.resumedb.jdo.*;

import javax.jdo.*;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;


public class MainClass extends Application {

    private final static String MainTitle = "ResumeDB " + MainClass.VERSION;
    private final static String VERSION = "v0.2";
    private final static String startFrameSource = "startFrame.fxml";
    private final static String addResumeSource = "addResumeFrame.fxml";
    private final static String sentResumeSource = "sentResumeDialog.fxml";
    private final static String showResumeStatusSource = "showResumeStatusDialog.fxml";


    private Mine mine = null;
    private ConcurrentMap<Long,Contact> catalog = null;
    private ConcurrentMap<Long, Resume> resumes = null;
    private ConcurrentMap<Long, List<resumeTracker>> history = null;
    private PersistenceManagerFactory pmf = null;
    private BlockingQueue<pipeMessage> pipe = new LinkedBlockingQueue(3);
    private static String pathDb = "192.168.0.3:3306/resumedb";

    public static void main(String[] args) {
        if (args.length == 1) {
            pathDb = args[0].trim();
        }
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {

        FXMLLoader loader = new FXMLLoader(getClass().getResource(startFrameSource));
        FXMLLoader loader1 = new FXMLLoader(getClass().getResource(addResumeSource));
        FXMLLoader loader2 = new FXMLLoader(getClass().getResource(sentResumeSource));
        FXMLLoader loader3 = new FXMLLoader(getClass().getResource(showResumeStatusSource));

        Parent root = (Parent) loader.load();
        Parent root1 = (Parent) loader1.load();
        Parent root2 = (Parent) loader2.load();
        Parent root3 = (Parent) loader3.load();

        assert root != null && root1 != null && root2 != null && root3 != null : "Файлы с фреймами должны загрузиться";

        MainFrameFXMLController controller = loader.getController();

        assert controller != null : "Окно не может быть без контроллера";

        Scene scene = new Scene(root);
        Scene addResumeScene = new Scene(root1);
        Stage addResumeStage = new Stage(StageStyle.UTILITY);
        Scene sentResumeScene = new Scene(root2);
        Stage sentResumeStage = new Stage(StageStyle.UTILITY);
        Scene showResumeStatusScene = new Scene(root3);
        Stage showResumeStatusStage = new Stage(StageStyle.UTILITY);
        addResumeStage.setScene(addResumeScene);
        addResumeStage.setTitle("Добавление нового резюме");
        addResumeStage.initOwner(stage);
        sentResumeStage.setScene(sentResumeScene);
        sentResumeStage.setTitle("Регистрация отправки резюме");
        sentResumeStage.initOwner(stage);
        showResumeStatusStage.setScene(showResumeStatusScene);
        showResumeStatusStage.setTitle("Статус резюме");
        showResumeStatusStage.initOwner(stage);


        controller.setStage(stage, controller, addResumeStage, sentResumeStage, showResumeStatusStage);
//        controller.setStage(stage, controller, null, null, null);
        stage.setScene(scene);
        stage.setTitle(MainTitle);
        stage.show();

        controller.setStatusbar("Загрузка данных");
        getDatabaseObjects();
        controller.setStatusbar("Операция по загрузке данных завершена");

        if (mine != null && catalog != null && resumes != null & history != null) {
            controller.setJDO(pmf, mine, catalog, resumes, history, pipe);
        }
        else {

            Dialogs dg = Dialogs.create();
            dg.owner(stage);
            dg.title("Ошибка доступа к базе данных");
            dg.masthead("Не удается получить доступ и восстановить объекты");
            dg.message("Неустранимая ошибка.  Программа будет закрыта");

            Action response = dg.showError();

            Platform.exit();

        }

        startBrowserService();

    }

    private void startBrowserService() {

        final BlockingQueue<pipeMessage> pipe = this.pipe;

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    if (Thread.interrupted()) break;
                    pipeMessage message;
                    try {
                        message = pipe.take();
                    } catch (InterruptedException e) {
                        break;
                    }
                    if (message == null || message.getData() == null || message.getType() == null) break;
                    String tempDir = System.getenv("TEMP");
                    String fileName = tempDir + "\\resume." + message.getType();

                    OutputStream fl;
                    try {
                        fl = new FileOutputStream(fileName);
                        fl.write(message.getData());
                        fl.close();
                        getHostServices().showDocument("file://"+fileName);
                    } catch (Exception e) {
                        Dialogs dg = Dialogs.create();
                        dg.title("Файловая ошибка");
                        dg.masthead("Не удается создать временный файл");

                        Action response = dg.showError();
                    }

                }
            }
        }).start();
     }

    private void getDatabaseObjects() {
//        PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("ResumeDB");


        Properties properties = new Properties();
        // properties.setProperty("javax.jdo.PersistenceManagerFactoryClass",
        //        "org.datanucleus.api.jdo.JDOPersistenceManagerFactory");
//        properties.setProperty("javax.jdo.option.ConnectionURL","excel:file:c:/resumedb/db.xls");
//        properties.setProperty("datanucleus.ConnectionURL", "neo4j:neo4jdb");
//        properties.setProperty("datanucleus.ConnectionDriverName", "org.apache.derby.jdbc.EmbeddedDriver");
        properties.setProperty("datanucleus.ConnectionDriverName", "com.mysql.jdbc.Driver");
//        String jdbcURI = "jdbc:derby:" + pathDb + ";create=true";
        String jdbcURI = "jdbc:mysql://" + pathDb + "?characterEncoding=utf-8&amp;connectionCollation=utf8_bin";
//        System.out.println(jdbcURI);
        properties.setProperty("datanucleus.ConnectionURL", jdbcURI);
        properties.setProperty("datanucleus.ConnectionUserName", "root");
        properties.setProperty("datanucleus.ConnectionPassword", "1234");
        properties.setProperty("datanucleus.identifier.case", "LowerCase");

        properties.setProperty("datanucleus.autoCreateSchema","true");
        properties.setProperty("datanucleus.validateTables","false");
        properties.setProperty("datanucleus.validateConstraints","false");
        properties.setProperty("datanucleus.DetachAllOnCommit","true");
        properties.setProperty("datanucleus.CopyOnAttach","false");
        this.pmf = JDOHelper.getPersistenceManagerFactory(properties);
        PersistenceManager pm = pmf.getPersistenceManager();

        Transaction tx = pm.currentTransaction();
        try {

            tx.begin();
            Query q = pm.newQuery(Mine.class);
            List<Mine> mnlist = (List<Mine>) q.execute();
            Iterator<Mine> iterator = mnlist.iterator();
            if (iterator.hasNext()) {
                mine = iterator.next();
            }
            else {

                mine = new Mine();

                pm.makePersistent(mine);

            }
            tx.commit();
        }
        finally {
            if (tx.isActive())
            {
                tx.rollback();
            }
            pm.close();
        }

        pm = pmf.getPersistenceManager();

        tx = pm.currentTransaction();
        try {
            tx.begin();
            Query q2 = pm.newQuery(Resume.class);
            List<Resume> list = (List<Resume>) q2.execute();

            resumes = new ConcurrentHashMap<>();
            Iterator<Resume> it = list.iterator();
            Resume r;
            while (it.hasNext()) {
                r = it.next();
                resumes.put(r.getId(), r);
            }

            tx.commit();
        }
        finally {
            if (tx.isActive())
            {
                tx.rollback();
            }
            pm.close();
        }

        pm = pmf.getPersistenceManager();

        tx = pm.currentTransaction();
        try {
            tx.begin();
            Query q1 = pm.newQuery(Contact.class);
            List<Contact> list = (List<Contact>) q1.execute();

            catalog = new ConcurrentHashMap<>();
            Iterator<Contact> it = list.iterator();
            Contact ct;
            while (it.hasNext()) {
                ct = it.next();
                catalog.put(ct.getId(), ct);
            }

            tx.commit();
        }
        finally {
            if (tx.isActive())
            {
                tx.rollback();
            }
            pm.close();
        }

        pm = pmf.getPersistenceManager();

        tx = pm.currentTransaction();
        try {
            tx.begin();
            Query q3 = pm.newQuery(resumeTracker.class);
            List<resumeTracker> list = (List<resumeTracker>) q3.execute();

            history = new ConcurrentHashMap<>();

            Iterator<resumeTracker> it = list.iterator();
            resumeTracker rt;
            while (it.hasNext()) {
                rt = it.next();
                if (history.get(rt.getResume()) == null) {
                    history.put(rt.getResume(), new LinkedList<resumeTracker>());
                }
                history.get(rt.getResume()).add(rt);
            }

            tx.commit();
        }
        finally {
            if (tx.isActive())
            {
                tx.rollback();
            }
            pm.close();
        }
    }


}
